﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using T.ServiceFramework.EventNotify;
using T.ServiceFramework.IOCService;
using T.ServiceFramework.Service;
using T.ServiceFramework.Spi;
using T.ServiceComponent.Cluster.Client;
using T.ServiceComponent.Kernel.Service;
using T.ServiceComponent.Runtime.Common.Utility;
using ServiceType = T.ServiceFramework.Spi.ServiceType;

namespace T.SF.Console
{
    internal class ProviderController
    {
        private static HostRestartWatcher hostRestartWatcher;
        public static void StartService()
        {
            var clusterTypeList = SFContext.Host.ClusterTypeList;
            if (clusterTypeList == null || clusterTypeList.Count == 0)
            {
                TSFLogger.Fatal("Get clusterTypeList length is 0。 HostID：" + SFContext.Host.ID);
                return;
            }

            TSFLogger.Info($" HostID:{SFContext.Host.ID}, ClusterID:{SFContext.Host.ClusterID}, ClusterTypeList:{{{string.Join(",", clusterTypeList)}}}");
            //注册包加载器
            PackageLoadService.Current.Init(SFContext.Host.ClusterID);

            PackageLoadService.Current.RegisterCommonPackage();

            foreach (var binding in SFContext.Host.BindingList)
            {
                MetadataService.Current.RegistMetadataLoader(binding.ServiceType, AssemblyHelper.CreateInstance<IServiceMetadataLoader>(binding.MetadataLoader));
                PackageLoadService.Current.Register(binding.ServiceType);
            }


            PackageLoadService.Current.OnLogPost += Current_OnLogPost;
            PackageLoadService.Current.OnServiceUpdated += Current_OnServiceUpdated;

            AssemblyFindService.Register();
            //PackageLoadService.Current.StartService();

            ///初始化IOC容器，初始化IOC容器要在服务包更新完之后。
            IOCService.Current.Init(clusterTypeList);

            var packages = PackageLoadService.Current.GetServiceLastedPackages();
            //AutoRunService.Current.Start(packages);

            foreach (var binding in SFContext.Host.BindingList)
            {
                ServiceProviderContainer.Current.RegisterProvider(binding, clusterTypeList, packages);
            }

            ServiceProviderContainer.Current.OnRestart += Current_OnRestart;
            ServiceProviderContainer.Current.OnLogPost += Current_OnLogPost;

            ServiceProviderContainer.Current.OnServiceLoaded += Current_OnServiceLoaded;
            var startResult = ServiceProviderContainer.Current.Start();

            //SG启动完以后再启动WEB服务
            if (startResult != null && startResult.SuccessList != null && startResult.SuccessList.Exists(svr => svr.ServiceType == ServiceType.SG))
            {
                HttpSelfHost.Current.OnStarted += (s) =>
                {
                    HostController.Current.ShowLogInfo(new LogInfo() { Level = LogLevel.Fatal, Message = ("Http Server Started @" + s) });
                };
                HttpSelfHost.Current.OnStoped += () =>
                {
                    HostController.Current.ShowLogInfo(new LogInfo() { Level = LogLevel.Fatal, Message = ("Http Server  Stoped !") });
                };

                System.Threading.Tasks.Task.Factory.StartNew(async () =>
                {
                     await HttpSelfHost.Current.Start(SFContext.Host.BindingList.FirstOrDefault(i => i.ServiceType == ServiceType.SG));
                }, System.Threading.Tasks.TaskCreationOptions.LongRunning);

            }


            if (AppConfig.IsLocalModel() == false)
            {
                ///进程重启事件
                hostRestartWatcher = new HostRestartWatcher(SFContext.Host.ID);
                hostRestartWatcher.OnHostRestart += Current_OnRestart;
                hostRestartWatcher.Start();


                ///暂时没啥用
                HostService.Current.HostStarted(SFContext.Host.ID);
            }

            ShowStartResult(startResult);
        }

        private static void Current_OnServiceUpdated(List<ServicePackage> servicePackages)
        {
            Current_OnRestart("ServicePackage Updated：" + JsonHelper.Serialize(servicePackages));
        }

        private static void ShowStartResult(StartResult startResult)
        {
            if (startResult.SuccessList != null && startResult.SuccessList.Count > 0)
            {
                ConsoleService.SetConsoleColor(ConsoleColor.Green);
                ConsoleService.Show("------------------------------" + Process.GetCurrentProcess().StartTime.ToString("yyyy-MM-dd HH:mm:ss") + " PID:" + Process.GetCurrentProcess().Id + "-----------------------------");
                startResult.SuccessList.ForEach(x =>
                {
                    if (x != null)
                        ConsoleService.Show("Service Host Started @" + Convert.ToString(x.ServiceType) + "://" + x.IP + ":" + x.Port);
                });
                var dic = ServiceProviderContainer.Current.GetLoadedServices();
                if (dic != null)
                {
                    StringBuilder sb = new StringBuilder(128);
                    foreach (var k in dic)
                    {
                        sb.Append(Convert.ToString(k.Key) + " Service started, total " + k.Value.Count + "; ");
                        k.Value.ForEach(x => ConsoleService.Show(Convert.ToString(k.Key) + " : " + x));
                    }
                    ConsoleService.Show(sb.ToString());
                    ConsoleService.Show("-------------------------------------------------------------------");
                }
                ConsoleService.ResetColor();
            }

            if (startResult.FailList != null && startResult.FailList.Count > 0)
            {
                ConsoleService.SetConsoleColor(ConsoleColor.Red);
                ConsoleService.Show("------------------------------" + Process.GetCurrentProcess().StartTime.ToString("yyyy-MM-dd HH:mm:ss") + " PID:" + Process.GetCurrentProcess().Id + "-----------------------------");
                startResult.FailList.Keys.ForEach(x => ConsoleService.Show("Service Host Start Failed @" + Convert.ToString(x.ServiceType) + "://" + x.IP + ":" + x.Port));
                ConsoleService.Show("Failed Reason:");
                startResult.FailList.Values.ForEach(x => ConsoleService.Show(x));
                ConsoleService.Show("-------------------------------------------------------------------");
            }

        }

        public static void ShowStartResult()
        {
            var result = ServiceProviderContainer.Current.GetStartInfo();
            ShowStartResult(result);
        }

        private static void Current_OnServiceLoaded(string metadataID)
        {
            TSFLogger.Info(metadataID + " Service Loaded！");
        }

        private static void Current_OnLogPost(LogInfo logInfo)
        {
            HostController.Current.ShowLogInfo(logInfo);
        }

        private static void Current_OnRestart(string reason)
        {
            HostController.Current.RaiseRestartEvent(reason);
        }

        public static void StopService()
        {
            try
            {
                PackageLoadService.Current.StopService();
            }
            catch (Exception e)
            {
                HostController.Current.ShowLogInfo(new LogInfo(e));
            }
            try
            {
                ServiceProviderContainer.Current.Stop();
                HttpSelfHost.Current.Stop();
            }
            catch (Exception e)
            {
                HostController.Current.ShowLogInfo(new LogInfo(e));
            }

        }
    }
}
